/*----------------------------------------------------------------------------
Owner(s): Shane Whitfield
$Copyright: $
$Id: $
----------------------------------------------------------------------------*/
#include "texture.h"
#include "map.h"
#include "camera.h"
#include "world.h"
#include "timermgr.h"
#include "render.h"
#include "touchmgr.h"

/* -------------------------------------------------------------------------*/
//globals
static bool (*s_fileLoader)(const char* i_filename, CMap* io_level) = 0 ;

/*--------------------------------------------------------------------------*/
CMapLocation::CMapLocation(const char* i_levelFileName, const Vector2f& i_pos)
{
	m_rotation = 0;
	m_worldMat.SetPos(i_pos);
	m_worldMat.SetScale(1.0f);
	
	SetLevelName(i_levelFileName);
	
	s_targetTexture = g_texturemgr.CreateTexture("map_target.png");
}

void CMapLocation::Update()
{
	m_rotation += M_PI * Dt();
	
	//spin pi a sec
	m_worldMat.SetRotation(m_rotation);
}

void CMapLocation::Render()
{
	g_texturemgr.EnableTextures(true);
	s_targetTexture->Apply();
	m_worldMat.PushMatrix();
	BasicDrawObjects::DrawTexturedRect(Vector2f(-0.15f, -0.15f), Vector2f(0.15f, 0.15f), Color4f(), Vector2f(0.0f, 0.0f), Vector2f(1.0f, 1.0f));
	m_worldMat.PopMatrix();
	g_texturemgr.EnableTextures(false);
}

bool CMapLocation::IsPointerWithin(const Vector2f& i_pos)
{
	///$$$$ This isn't quite right... we should re do this to be a point in box text
	return Dist(i_pos, m_worldMat.GetPos()) <= 0.3f;
}

/*--------------------------------------------------------------------------*/

void CMap::SetFileLoader(bool (*systemFileLoader)(const char* i_filename, CMap* io_map))
{
    s_fileLoader = systemFileLoader;
}

CMap::CMap(const char* i_fileName)
{
	m_state = EState_OffScreen;
	m_tState = T();
	m_mapBackGround = g_texturemgr.CreateTexture("missing_texture.png");
	m_worldMat.SetPos(Vector2f::Zero);
	m_worldMat.SetScale(1.0f);
	m_lastMapRequestIndex = -1;
	m_unlocked = true;
	
	s_fileLoader(i_fileName, this);
}

CMap::~CMap()
{
	for (int iLocation = 0; iLocation < m_mapLocations.size(); ++iLocation)
	{
		delete m_mapLocations[iLocation];
	}
	
	m_mapLocations.clear();
}

void CMap::Render()
{	
	g_texturemgr.EnableTextures(true);
	m_mapBackGround->Apply();
	m_worldMat.PushMatrix();
	
	Color4f color;
	switch(m_state)
	{
	case EState_Previous:
	case EState_Next:
		{
			color.a = 0.5f;
		}
		break;
	}
	
	BasicDrawObjects::DrawTexturedRect(m_min, m_max, color, Vector2f(0.0f, 0.0f), Vector2f(1.0f, 1.0f));
	m_worldMat.PopMatrix();
	g_texturemgr.EnableTextures(false);
	
	if (m_state == EState_Current)
	{
		for (int iLocation = 0; iLocation < m_mapLocations.size(); ++iLocation)
		{
			if (m_mapLocations[iLocation]->IsUnlocked())
			{
				m_mapLocations[iLocation]->Render();
			}
		}
	}
}

void CMap::Update()
{
	for (int iLocation = 0; iLocation < m_mapLocations.size(); ++iLocation)
	{
		if (m_mapLocations[iLocation]->IsUnlocked())
		{
			m_mapLocations[iLocation]->Update();
			
			Vector2f worldTouch = g_touchmgr.GetTouchEventWorldPos(ETouchType_DoubleTapStart);
			if (g_touchmgr.HasTouchEvent(ETouchType_DoubleTapStart, false) &&
				m_mapLocations[iLocation]->IsPointerWithin(worldTouch))
			{
				m_lastMapRequestIndex = iLocation;
				g_world.RequestLoad(m_mapLocations[iLocation]->GetLevelName());
			}
		}
	}
}

void CMap::On_LocationLoad(const char* i_levelFileName, float i_x, float i_y, bool unlocked)
{
	CMapLocation* newMapLoc = new CMapLocation(i_levelFileName, Vector2f(i_x, i_y));
	newMapLoc->SetUnlocked(unlocked);
	m_mapLocations.push_back(newMapLoc);
}

void CMap::On_ImageLoad(const char* i_imageFileName)
{
	m_mapBackGround = g_texturemgr.CreateTexture(i_imageFileName);
}

void CMap::UnlockNextLevel()
{
	//if we just completed the last one.. then we should unlock the next map
	if (m_mapLocations.size() > m_lastMapRequestIndex + 1)
	{
		m_mapLocations[m_lastMapRequestIndex + 1]->SetUnlocked(true);
	}
}

void CMap::ScaleLeft()
{
	switch(m_state)
	{
	case EState_Previous:
		{
			setState(EState_OffScreen);
		}
		break;
	case EState_Current:
		{
			setState(EState_Previous);
		}
		break;
	case EState_Next:
		{
			setState(EState_Current);
		}
		break;
	}
}

void CMap::ScaleRight()
{
	switch(m_state)
	{
	case EState_Previous:
		{
			setState(EState_Current);
		}
		break;
	case EState_Current:
		{
			setState(EState_Next);
		}
		break;
	case EState_Next:
		{
			setState(EState_OffScreen);
		}
		break;
	}
}

void CMap::setState(EState i_state)
{
	m_state = i_state;
	m_tState = T();
	
	switch(m_state)
	{
	case EState_Previous:
		{
			m_min = Vector2f(-1.4, -1.5f);
			m_max = Vector2f(1.4f, 1.5f);
			m_worldMat.SetPos(Vector2f(-0.85f, -1.1f));
			m_worldMat.SetScale(0.15f);
		}
		break;
	case EState_Current:
		{
			m_min = Vector2f(-1.4, -1.5f);
			m_max = Vector2f(1.4f, 1.5f);
			m_worldMat.SetPos(Vector2f::Zero);
			m_worldMat.SetScale(1.0f);
		}
		break;
	case EState_Next:
		{
			m_min = Vector2f(-1.4, -1.5f);
			m_max = Vector2f(1.4f, 1.5f);
			m_worldMat.SetPos(Vector2f(0.85f, -1.1f));
			m_worldMat.SetScale(0.15f);
		}
		break;
	}
}

bool CMap::IsPointWithin(const Vector2f& i_touchPos, const Vector2f& i_worldTouchPos) const
{
	if (Dist(i_worldTouchPos, m_worldMat.GetPos()) <= m_worldMat.GetScale())
	{
		return true;
	}
	return false;
}

/*--------------------------------------------------------------------------*/

CMapMgr::CMapMgr() : super("mapmgr")
{
	m_state = EState_Inactive;
	m_mapRequested = false;
	m_curMapIndex = 0;
	m_maxMaps = 2;
	
	m_backGround = g_texturemgr.CreateTexture("map_background.png");
	m_worldMat.SetPos(Vector2f::Zero);
	m_worldMat.SetScale(1.0f);
	
	setCurrentMapIndex(0);
}

CMapMgr::~CMapMgr()
{
	for (int iMap = 0; iMap < m_maps.size(); ++iMap)
	{
		delete m_maps[iMap];
	}
	
	m_maps.clear();
}

CMap* CMapMgr::getCurMap()
{
	if (m_curMapIndex < 0 || m_curMapIndex > m_maps.size())
	{
		printf("ERROR: invaild map index!");
		return NULL;
	}
	
	return m_maps[m_curMapIndex];
}

void CMapMgr::setCurrentMapIndex(int i_mapIndex)
{
	m_curMapIndex = i_mapIndex;
}

void CMapMgr::OnInit()
{
	const char* mapNames[] = {"tutorial.map", "monkey.map"};
	
	for (int iMap = 0; iMap < m_maxMaps; ++iMap)
	{
		m_maps.push_back(new CMap(mapNames[iMap]));
	}
	
	//after we have loaded all the levels.. for the first to be current and the
	// second to be the next level
	if (m_maps.size() > 0)
	{
		m_maps[0]->ForceAsCurrentLevel();
	}
	if (m_maps.size() > 1) 
	{
		m_maps[1]->ForceAsNextLevel();
	}
}

void CMapMgr::Render()
{
	switch (m_state)
	{
	case EState_Active:
		{
			//render the background
			Vector2f mmin(-1.4,-1.5f), mmax(1.4f, 1.5f);
			g_texturemgr.EnableTextures(true);
			m_backGround->Apply();
			m_worldMat.PushMatrix();
			BasicDrawObjects::DrawTexturedRect(mmin, mmax, Color4f(), Vector2f(0.0f, 0.0f), Vector2f(1.0f, 1.0f));
			m_worldMat.PopMatrix();
			g_texturemgr.EnableTextures(false);
			
			getCurMap()->Render();
			
			//if there is a previous map.. render it
			if (m_curMapIndex != 0)
			{
				m_maps[m_curMapIndex - 1]->Render();
			}
			
			//if there is a next map.. render it
			if (m_curMapIndex < m_maps.size() - 1)
			{
				m_maps[m_curMapIndex + 1]->Render();
			}
		}
		break;
	}
}

void CMapMgr::Update()
{
	switch (m_state)
	{
	case EState_Active:
		{
			if (getCurMap())
			{
				getCurMap()->Update();
			}
			
			if (g_touchmgr.HasTouchEvent(ETouchType_DoubleTapStart, false))
			{
				Vector2f touchPos = g_touchmgr.GetTouchEventScreenPos(ETouchType_DoubleTapStart);
				Vector2f worldTouchPos = g_touchmgr.GetTouchEventWorldPos(ETouchType_DoubleTapStart);
				
				//was the previous map clicked?
				if (HasPreviousMap() && m_maps[m_curMapIndex - 1]->IsPointWithin(touchPos, worldTouchPos))
				{
					m_maps[m_curMapIndex - 1]->ScaleRight();
					m_maps[m_curMapIndex]->ScaleRight();
					
					if (HasNextMap())
						m_maps[m_curMapIndex + 1]->ScaleRight();
					
					m_curMapIndex--;
				}
				
				//was the next map clicked? 
				if (HasNextMap() && m_maps[m_curMapIndex + 1]->IsPointWithin(touchPos, worldTouchPos))
				{
					if (HasPreviousMap())
						m_maps[m_curMapIndex - 1]->ScaleLeft();
						
					m_maps[m_curMapIndex]->ScaleLeft();
					
					m_maps[m_curMapIndex + 1]->ScaleLeft();
					
					m_curMapIndex++;
				}
			}
		}
		break;
	}
}

void CMapMgr::setState(EState i_state)
{
	m_state = i_state;
}

void CMapMgr::UnlockNextLevel()
{
	if (getCurMap())
	{
		getCurMap()->UnlockNextLevel();
	}
}

/*-----------------------------------EOF!-----------------------------------*/ 
